package com.stephen.interceptor;

import com.stephen.annotation.AccessLimit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeUnit;

public class FangShuaInterceptor extends HandlerInterceptorAdapter {

    FangShuaInterceptor(){
        System.out.println("------------执行接口防刷拦截器---------------");
    }

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public boolean preHandle(HttpServletRequest request , HttpServletResponse response , Object handler) throws Exception {


        if (handler instanceof HandlerMethod) {

            HandlerMethod handlerMethod = (HandlerMethod) handler;

            AccessLimit accessLimit = handlerMethod.getMethodAnnotation(AccessLimit.class);
            // 如果没有该注解，则不在防刷目标里，直接返回
            if (accessLimit == null) {
                return true;
            }
            // 获取最大访问次数
            int maxAccessCnt = accessLimit.maxCount();
            //获取允许最大访问的时间
            int seconds = accessLimit.seconds();
            // 获取ip
            String key = getRealIp(request);
            // ip+请求的接口路径 => 唯一标识key
            key += request.getRequestURI();

            //当前访问次数
            Object value = redisTemplate.opsForValue().get(key);

            if (value == null) {
                //第一次访问 设置key保留时长为1s
                redisTemplate.opsForValue().set(key, 1, seconds, TimeUnit.SECONDS);

            } else {

                Integer currentCnt = (Integer) value;
                if (currentCnt < maxAccessCnt) {
                    //对应key值自增
                    redisTemplate.opsForValue().increment(key);
                } else {
                    //超出接口时间段内允许访问的次数，直接返回错误信息,同时设置过期时间 20s自动剔除
                    redisTemplate.expire(key, 5,TimeUnit.SECONDS);
                    response.setContentType("application/json;charset=utf-8");
                    try {
                        OutputStream out = response.getOutputStream();
                        out.write("访问次数已达上线！请稍后再访问".getBytes(StandardCharsets.UTF_8));
                        out.flush();
                        out.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    return false;
                }
            }
        }
        return true;
    }

    private String getRealIp(HttpServletRequest request) {
        StringBuffer requestURL = request.getRequestURL();
        String path = requestURL.toString();
        String[] split1 = path.split("//");
        String[] split2 = split1[1].split("/");
        String[] result = split2[0].split(":");
        return result[0];
    }

}
